ext.define('extension.gui', function() {

function expoInOut(n) {
    if (n == 1)
        return 1;
    var x = n * 2;
    if (x < 1)
        return Math.pow(2, 10 * (x - 1)) / 2;
    return (-Math.pow(2, -10 * --x) + 2) / 2;
}

function scrollTo(to, callback) {
    var start = window.performance.now(),
        target = document.body,
        from = target.scrollTop,
        length = to - from;

    function end() {
        if (callback != null)
            callback();
    }

    function scroll(now) {
        var time = Math.min(1, (now - start) / 460);
        target.scrollTop = expoInOut(time) * length + from;
        if (time < 1)
            window.requestAnimationFrame(scroll);
        else
            end();
    }

    if (from != to)
        window.requestAnimationFrame(scroll);
    else
        end();
}

return {
    scrollTo: scrollTo
};

});

ext.define('extension.gui', function() {

var target = null;
var anchor = {};
var click = {};

function eventHandler(event) {
    event.preventDefault();
    event.stopPropagation();
    switch (event.type) {
        case 'mousedown':
            click.x = event.clientX;
            click.y = event.clientY;
            anchor.left = target.offsetLeft;
            anchor.top = target.offsetTop;
            document.addEventListener('mousemove', eventHandler, true);
            document.addEventListener('mouseup', eventHandler, true);
            break;
        case 'mousemove':
            if (click.x != event.clientX && click.y != event.clientY) {
                var style = target.style;
                style.left = (anchor.left + event.clientX - click.x) + 'px';
                style.top = (anchor.top + event.clientY - click.y) + 'px';
                style.right = style.bottom = 'auto';
            }
            break;
        case 'mouseup':
            document.removeEventListener('mousemove', eventHandler, true);
            document.removeEventListener('mouseup', eventHandler, true);
    }
}

function attachAchorPoint(sourceElement, targetElement) {
    target = targetElement;
    sourceElement.addEventListener('mousedown', eventHandler, true);
}

return {
    attachAchorPoint: attachAchorPoint
};

});
